;(function () {
  //先阻止微信浏览器下拉
  // document.body.addEventListener('touchmove' , function(e){
  //     e.preventDefault();
  // },true);

  var pi = Math.PI,
    ww = window.innerWidth,
    wh = window.innerHeight,
    stickWidth = Math.floor(ww * 0.3),
    transformReg = /transform[^;]*;|-webkit-transform[^;]*;/g,
    transformTemp =
      '-webkit-transform: translate(JS_x_px,JS_y_px);transform: translate(JS_x_px,JS_y_px);' //摇杆的宽度

  /**
   * 摇杆
   * */
  function Joystick(eventEl, domHidden) {
    this.eventEl = eventEl
    this.dom = ''
    this.domI = ''
    this.domHidden = domHidden

    this.area = 'left' //触发区域，left：左半边屏幕

    this.enabled = true

    this.startP = false //[id,x,y] 本次移动的开始位置，会把摇杆挪到此位置。id是点的id，只有这个点移动，才是本摇杆的
    this.hasEvent = false

    if (!domHidden) this.addTo()
  }

  var p = Joystick.prototype

  p.addTo = function (cla) {
    var html = (
      '<div class="joystick" style="position: absolute; bottom: 10%; left: 10%; width: JS_stickWidth_px; height: JS_stickWidth_px; background: #000; opacity: .3; border-radius: 50%; border: 5px solid #fff;">' +
      '<div style="position: absolute; top: 50%; left: 50%;">' +
      '<i style="display: block;width: JS_sw_px; height: JS_sw_px; border-radius: 50%; border: 2px solid #000; background: #fff;-webkit-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); -o-transform: translate(-50%, -50%); transform: translate(-50%, -50%);"></i>' +
      '</div>' +
      '</div>'
    )
      .replace(/JS_stickWidth_/g, stickWidth)
      .replace(/JS_sw_/g, stickWidth * 0.3)

    this.dom = parseToDOM(html)
    this.domI = this.dom.children[0]

    var addTo = cla ? document.querySelector(cla) : this.eventEl
    addTo.appendChild(this.dom)
  }

  //隐藏控制器（但控制能力依然有）
  p.hideDom = function () {
    this.domHidden = true
    this.dom.style.display = 'none'
  }

  //停止控制
  p.stop = function () {
    this.enabled = false
  }

  //当摇杆状态发生变化时，回调参数1：弧度，0是正前，90是正右。回调参数2：速度，取值0到1，保留两位小数。
  // ps. 速度为0时，理论上是没有角度的，但是这里会返回速度为0前最后的角度
  p.onJoystickChange = function (fn) {
    var t = this
    if (!t.hasEvent) {
      t.eventEl.addEventListener(
        'touchstart',
        function (e) {
          touchstart(e, t)
        },
        false
      )
      t.eventEl.addEventListener(
        'touchmove',
        function (e) {
          touchmove(e, t, fn)
        },
        false
      )
      t.eventEl.addEventListener(
        'touchend',
        function (e) {
          touchmove(e, t, fn, true)
        },
        false
      )

      t.eventEl.addEventListener(
        'mousedown',
        function (e) {
          touchstart(e, t)
        },
        false
      )
      t.eventEl.addEventListener(
        'mousemove',
        function (e) {
          touchmove(e, t, fn)
        },
        false
      )
      t.eventEl.addEventListener(
        'mouseup',
        function (e) {
          touchmove(e, t, fn, true)
        },
        false
      )

      t.hasEvent = true
    }
  }

  function touchstart(e, t) {
    if (!t.enabled || t.startP) return

    var k = 'page',
      touches = e.touches || [e], //mousedown事件的pageX等，是直接在e下面的
      id = -1, //这个是记录点的id，一轮touch事件下来，一个点的id是固定不变的
      x = -1,
      y = -1,
      i = 0

    var ids = []

    //要选一个对的点
    for (; i < touches.length; i++) {
      id = touches[i].identifier
      x = touches[i][k + 'X']
      y = touches[i][k + 'Y']
      ids.push(id)
    }

    t.startP = (id >= 0 || !e.touches) && [id, x, y]
  }
  function touchmove(e, t, fn, isEnd) {
    // e.preventDefault();
    // e.stopPropagation();
    if (!t.enabled || !t.startP) return

    var k = 'page',
      touches = e.changedTouches || [e], //这个是触发此事件的点数组
      i = 0

    var p = false

    for (; i < touches.length; i++) {
      if (touches[i].identifier === t.startP[0]) {
        p = [touches[i].identifier, touches[i][k + 'X'], touches[i][k + 'Y']]
        break
      }
    }

    if (!p) return

    if (!t.domHidden)
      t.domI.style.cssText = t.domI.style.cssText.replace(transformReg, '')
    if (isEnd) {
      t.startP = false
      fn(0, 0)
    } else {
      var x = p[1] - t.startP[1],
        y = p[2] - t.startP[2],
        thirdLength = Math.abs(
          (x === 0 && y) ||
            (y === 0 && x) ||
            Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
        ) //斜边长度

      var angle = 0
      if (!((x === 0 && y === 0) || (x === 0 && y < 0))) {
        if (x === 0 && y > 0) angle = pi
        else if (y === 0 && x > 0) angle = pi / 2
        else if (y === 0 && x < 0) angle = pi * 1.5
        else {
          angle = Math.atan(Math.abs(x / y))
          if (x > 0 && y > 0) {
            angle = pi - angle
          } else if (x < 0 && y > 0) {
            angle += pi
          } else if (angle && x < 0 && y < 0) {
            angle = pi * 2 - angle
          }
        }
      }

      fn(
        angle,
        Math.round(Math.min(1, (thirdLength / stickWidth) * 2) * 100) / 100
      )

      if (!t.domHidden) {
        var lengthScale = stickWidth / 2 / thirdLength
        //要确认终点是不是在摇杆圈内
        if (lengthScale < 1) {
          x *= lengthScale
          y *= lengthScale
        }
        t.domI.style.cssText += transformTemp
          .replace(/JS_x_/g, x)
          .replace(/JS_y_/g, y)
      }
    }
  }

  function parseToDOM(str) {
    var div = document.createElement('div')
    div.innerHTML = str
    return div.children.length > 1 ? div.children : div.children[0]
  }

  window.Joystick = Joystick
})()
